using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using Pasta.Medio.Abstract;
using Pasta.Medio.Concrete;
using Pasta.Medio.Configuration;
using Pasta.Medio.Controls;
using Pasta.Medio.Dialogs;
using Pasta.Medio.Domain;
using Pasta.Medio.Models;
using Pasta.Medio.Properties;

namespace Pasta.Medio
{
	public partial class MedioShell : Form
	{
		private AppSettings Settings = Program.Settings;
		private DriveDetector _detector;
		private DriveInfo _drive;
		private SortableBindingList<Recording> Catalog = Program.Catalog;
		private Results _results = new Results();

		private List<Error> _errors = new List<Error>();

		private IMediaScanner scanner;

		public MedioShell(string[] args)
		{
			InitializeComponent();

			if (Settings.HasErrors)
			{
				MessageBox.Show("There are errors in the settings");
				//ShowErrors();
				Environment.Exit(-1);
			}
		}

		private void MedioShell_Load(object sender, EventArgs e)
		{
			// add the tabs
			tabDeck.AddTab<CatalogTab>("Catalog");
			tabDeck.AddTab<ScanTab>("Scan");
			tabDeck.AddTab<SettingsTab>("Settings");

			// initialize drive detector
			//_detector = new DriveDetector();
			//_detector.DriveInserted += _detector_DeviceArrived;
			//_detector.DriveRemoved += _detector_DeviceRemoved;

			PrepareDash();

			//lblTotalImages.Text = Catalog.Count.ToString();
		}

		void _detector_DeviceArrived(object sender, DriveDetectorEventArgs e)
		{
			MessageBox.Show("Drive " + e.Drive + " inserted");
			if (e.Drive == _drive.Name)
			{
			}
		}

		#region Messages and Events               - - - - - - - - - - - - - - - - - - - - - - - - -

		private void ChangeTab(object sender, EventArgs e)
		{
			ToolStripButton btn = sender as ToolStripButton;
			tabDeck.SelectTab(btn.Text);
		}

		private void tsDash_Click(object sender, EventArgs e)
		{
			tabDeck.SelectTab("Dashboard");
		}

		private void tsCatalog_Click(object sender, EventArgs e)
		{
			tabDeck.SelectTab("Catalog");
		}

		private void tsbScan_Click(object sender, EventArgs e)
		{
			tabDeck.SelectTab("Scan");
		}

		private void tsSettings_Click(object sender, EventArgs e)
		{
			tabDeck.SelectTab("Settings");
		}

		private void PrepareDash()
		{
			//lblImageLibrary.Text = Settings.ImageFolder;
			//lblVideoLibrary.Text = Settings.VideoFolder;

			var imageTypes = from m in Catalog.Where(r => r.TypeEnum == (int)Enums.Type.Image)
							 group m by Path.GetExtension(m.Name).Substring(1) into grp
							 select new { Type = grp.Key, Count = grp.Count() };
			dashImageChart.Series["Types"].Points.DataBind(imageTypes, "Type", "Count", null);

			var videoTypes = from m in Catalog.Where(r => r.TypeEnum == (int)Enums.Type.Video)
							 group m by Path.GetExtension(m.Name).Substring(1) into grp
							 select new { Type = grp.Key, Count = grp.Count() };
			dashVideoChart.Series["Types"].Points.DataBind(videoTypes, "Type", "Count", null);

			Stopwatch sw = new Stopwatch();
			sw.Restart();
			CountFiles(Settings.VideoFolder);
			sw.Stop();
			MessageBox.Show( String.Format("{0} files scanned in {1:0.00} sec", _recordings.Count, sw.ElapsedMilliseconds/1000.0));
		}

		List<MediaView> _recordings = new List<MediaView>();

		public void CountFiles(string path)
		{
			try
			{
				var files = Settings.MediaTypes.SelectMany(ext2 => Directory.GetFiles(path, ext2));
				foreach (var file in files)
				{
					var mv = new MediaView(file,0);
					_recordings.Add(mv);
					mv.InCatalog = Catalog.Any(r => r.Name.ToLower() == Path.GetFileName(file).ToLower());
					FileInfo fi = new FileInfo(file);
					mv.Size = fi.Length;
				}
			}
			catch { }
			try
			{
				foreach (string folder in Directory.GetDirectories(path))
				{
					CountFiles(folder);
				}
			}
			catch { }
		}

		private void tsCancel_Click(object sender, EventArgs e)
		{
			if (scanner != null)
			{
				scanner.Cancel();
			}
		}

		#endregion                                - - - - - - - - - - - - - - - - - - - - - - - - -

		private bool ImportRecording(MediaView media, MedioEntities db)
		{
			bool result = false;
			try
			{
				media.Selected = false;
				string folder = Settings.IncomingImages;
				string stagingPath = Path.Combine(folder, media.TargetName);
				folder = media.Type == Enums.Type.Image ? Settings.ImageFolder : Settings.VideoFolder;
				string targetPath = Path.Combine(folder, media.TargetName);
				if (!File.Exists(targetPath) && !File.Exists(stagingPath))
				{
					File.Copy(media.Path, stagingPath);
					media.Sha1 = Util.ComputeSHA1(stagingPath);
					media.Selected = true;
				}
				var rec = db.Recordings.FirstOrDefault(m => m.Size == media.Size && m.Sha1 == media.Sha1);
				if (!media.Selected || rec != null)
				{
					media.Selected = false;
					//_errors.AddError(ErrorType.MediaFile, Severity.Warning, "File {0} was already imported on {1}", rec.Name, rec.CatalogedOn);
					File.Delete(targetPath);
				}
				else
				{
					MediaView mv = new MediaView
					{
						//Type = media.Type.ToString().Substring(0, 1),
						//CameraEnum = media.VolumeLabel,
						//SourcePath = media.SourcePath,
						Path = media.Path,
						TargetName = media.TargetName,
						RecordedOn = media.RecordedOn,
						Size = media.Size,
						Sha1 = media.Sha1
					};
					//db.Media.AddObject(rec);
					db.SaveChanges();
					File.Move(stagingPath, targetPath);
					result = true;
				}
			}
			catch (IOException ex)
			{
				//_errors.AddError(ErrorType.MediaFile, Severity.Error, "Unable to copy file {0}", ex.Message);
			}
			catch (Exception ex)
			{
				//_errors.AddError(ErrorType.MediaFile, Severity.Error, "Error analyzing file: {0}", ex.Message);
			}
			return result;
		}

		private bool ShowErrors(Results results)
		{
			if (!results.Success)
			{
				//Environment.Exit(-1);
			}
			return results.Success;
		}

		private void SetLabel(Label label, string text, params object[] args)
		{
			if (this.InvokeRequired)
			{
				Invoke((MethodInvoker)delegate
				{
					label.Text = String.Format(text, args);
					Application.DoEvents();
				});
			}
			else
			{
				label.Text = String.Format(text, args);
			}
		}

		private void SetStatus(string text, params object[] args)
		{
			if (this.InvokeRequired)
			{
				Invoke((MethodInvoker)delegate
				{
					tsLabel.Text = String.Format(text, args);
					Application.DoEvents();
				});
			}
			else
			{
				tsLabel.Text = String.Format(text, args);
			}
		}

		private void tabDeck_SelectedIndexChanged(object sender, EventArgs e)
		{
		}
	}

	/*
		DriveInfo[] drives = DriveInfo.GetDrives();
		foreach (var drive in drives.Where(d => d.IsReady))
		{
			bt.SharedProps.Caption = drive.Name;
		}

		public static IEnumerable<string> GetFiles(string path, string[] searchPatterns, SearchOption searchOption = SearchOption.TopDirectoryOnly)
		{
			return searchPatterns.AsParallel().SelectMany(searchPattern => Directory.EnumerateFiles(path, searchPattern, searchOption));
		}
	 
		private DriveInfo GetDriveInfo(char name)
		{
			DriveInfo[] drives = DriveInfo.GetDrives();
			return drives.Where(d => d.Name[0] == name).FirstOrDefault();
		}

	*/
}
